package utils

import (
	"fmt"
	"net"
	"net/url"
	"strconv"
	"strings"
	"time"
)

// IsValidIP
// 检测IP地址是否合法
func IsValidIP(ipAddr string) bool {
	return net.ParseIP(ipAddr) != nil
}

// IsValidPort
// 检测端口是否合法
func IsValidPort(port string) (int, error) {
	p, err := strconv.Atoi(port)
	if err != nil {
		return 0, fmt.Errorf("port conversion error: %v", err)
	}
	if p < 1 || p > 65535 {
		return 0, fmt.Errorf("port number out of range: %d", p)
	}
	return p, nil
}

// IsValidURL
// 检测给定字符串是否是一个合法的URL。
func IsValidURL(u string) bool {
	// 尝试解析URL
	parsed, err := url.ParseRequestURI(u)
	if err != nil {
		return false // 解析失败意味着这不是一个合法的URL
	}

	// 判断解析后的URL是否包含Host字段，常用来判断URL是否合法
	return parsed.Scheme != "" && parsed.Host != ""
}

// Ping
// 对目的地址发起ping检测icmp是否通畅（只支持ipv4）
func Ping(ipAddr string, timeout time.Duration) bool {
	conn, err := net.DialTimeout("ip4:icmp", ipAddr, timeout)
	if err != nil {
		return false
	}

	_ = conn.Close()
	return true
}

// DetectTcpPort
// 检测Tcp端口是否开通
func DetectTcpPort(ip string, port int, timeout time.Duration) bool {
	address := fmt.Sprintf("%s:%d", ip, port)
	conn, err := net.DialTimeout("tcp", address, timeout)
	if err != nil {
		return false
	}

	// 建立后关闭连接
	defer func(conn net.Conn) {
		_ = conn.Close()
	}(conn)

	return true
}

// CalculateNetwork
// 根据给定的IP地址和子网掩码计算网络地址
func CalculateNetwork(ipAddr, subnetMask string) (string, error) {
	// 解析IP地址和子网掩码
	ip := net.ParseIP(ipAddr)
	if ip == nil {
		return "", fmt.Errorf("invalid IP address format")
	}
	mask := net.IPMask(net.ParseIP(subnetMask)[12:])
	if mask == nil {
		return "", fmt.Errorf("invalid subnet mask format")
	}

	// 计算网络地址
	network := net.IPNet{IP: ip.Mask(mask), Mask: mask}
	return network.IP.String(), nil
}

// SubNetMaskToBits
// 将子网掩码转换为掩码位数
func SubNetMaskToBits(subnetMask string) (int, error) {
	ip := net.ParseIP(subnetMask)
	if ip == nil {
		return 0, fmt.Errorf("invalid subnet mask")
	}
	// 将IP地址转换为4字节（对于IPv4）或16字节（对于IPv6）的表示
	mask := ip.To4()
	if mask == nil {
		return 0, fmt.Errorf("invalid IPv4 subnet mask")
	}
	// 计算子网掩码中1的总数
	bits := 0
	for _, octet := range mask {
		for octet > 0 {
			bits += int(octet & 1) // 如果最低位是1，计数器增加
			octet >>= 1            // 向右移位，检查下一个位
		}
	}
	return bits, nil
}

// BitsToSubNetMask
// 将掩码位数转换为子网掩码
func BitsToSubNetMask(maskBits int) (string, error) {
	if maskBits < 0 || maskBits > 32 {
		return "", fmt.Errorf("invalid subnet bits: %d", maskBits)
	}
	// 根据掩码位计算子网掩码
	var mask uint32 = ^uint32(0) << (32 - maskBits)
	return fmt.Sprintf("%d.%d.%d.%d", mask>>24, (mask>>16)&0xFF, (mask>>8)&0xFF, mask&0xFF), nil
}

// IpAddressConvertToInt
// 将IP地址转换为整数
func IpAddressConvertToInt(ip string) (int, error) {
	if !IsValidIP(ip) {
		return -1, fmt.Errorf("invalid IP address format")
	}
	ipSegs := strings.Split(ip, ".")
	result := 0
	for i, v := range ipSegs {
		seg, _ := strconv.Atoi(v)
		seg <<= (3 - i) * 8
		result |= seg
	}
	return result, nil
}

// IntConvertToIpAddress
// 将整数转换为IP地址
func IntConvertToIpAddress(ipInt int) (string, error) {
	var ipSegs []string
	for i := 0; i < 4; i++ {
		seg := ipInt >> ((3 - i) * 8) & 255
		ipSegs = append(ipSegs, strconv.Itoa(seg))
	}
	result := strings.Join(ipSegs, ".")
	if !IsValidIP(result) {
		return "", fmt.Errorf("invalid IP address format")
	}
	return result, nil
}
